package com.quality.web.server.misc;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.json.simple.*;

public final class JSONComposer {

  private JSONComposer() {
    super();
  }

  public static final String RESULT = "response";
  public static final String SUCCESS = "success";
  public static final String FAILURE = "failure";
  public static final String DATA = "data";

  private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
      "yyyy-MM-dd");

  private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat(
      "yyyy-MM-dd HH:mm:ss");

  @SuppressWarnings("unchecked")
  public static String compose(String key, String message) {
    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, SUCCESS);
    jsonRoot.put(key, message);
    return JSONComposer.jsonString(jsonRoot);
  }

  @SuppressWarnings("unchecked")
  private static String compose(String key, Number number) {
    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, SUCCESS);
    jsonRoot.put(key, number);
    return JSONComposer.jsonString(jsonRoot);
  }

  public static String compose(Number number) {
    return JSONComposer.compose(DATA, number);
  }

  public static String compose(String message) {
    return JSONComposer.compose(DATA, message);
  }

  @SuppressWarnings("unchecked")
  public static String compose(String key, JSONAware json) {
    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, SUCCESS);
    jsonRoot.put(key, json);
    return JSONComposer.jsonString(jsonRoot);
  }

  public static String compose(JSONAware json) {
    return JSONComposer.compose(DATA, json);
  }

  @SuppressWarnings("unchecked")
  public static String compose(String key, JSONArray jsonArray) {
    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, SUCCESS);
    jsonRoot.put(key, jsonArray);
    return JSONComposer.jsonString(jsonRoot);
  }

  public static String compose(JSONArray jsonArray) {
    return JSONComposer.compose(DATA, jsonArray);
  }

  @SuppressWarnings("unchecked")
  public static String compose(String key, JSONObject jsonObject) {
    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, SUCCESS);
    jsonRoot.put(key, jsonObject);
    return JSONComposer.jsonString(jsonRoot);
  }

  @SuppressWarnings("unchecked")
  public static String composeError(String errorMessage) {
    ServerLogger.error(errorMessage);

    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, FAILURE);
    jsonRoot.put(DATA, errorMessage);
    return JSONComposer.jsonString(jsonRoot);
  }

  public static String composeError(Exception e) {
    ServerLogger.error("Unexpected error : " + e.getClass().getName(), e);

    return JSONComposer.composeError(e.getMessage());
  }

  @SuppressWarnings("unchecked")
  public static String compose(String[] keys, JSONAware[] values) {
    JSONObject jsonData = new JSONObject();
    jsonData.put("status", "0");
    jsonData.put("startRow", "0");
    jsonData.put("endRow", "2");
    jsonData.put("totalRows", "2");
    for (int i = 0; i < keys.length; i++) {
      jsonData.put(keys[i], values[i]);
    }

    JSONObject jsonRoot = new JSONObject();
    jsonRoot.put(RESULT, jsonData);
    return JSONComposer.jsonString(jsonRoot);
  }

  // /////////////////////
  // FORMATTERS/PARSERS //
  // /////////////////////

  public static String currentDate() {
    return DATE_FORMAT.format(new Date(System.currentTimeMillis()));
  }

  public static String formatBoolean(Boolean b) {
    return (b == null) ? null : b.toString();
  }

  public static String formatDate(Date date) {
    if (date == null) {
      return null;
    }
    return DATE_FORMAT.format(date);
  }

  public static String formatTimestamp(Date date) {
    if (date == null) {
      return null;
    }
    return TIMESTAMP_FORMAT.format(date);
  }

  // this is here to centralize all toJSONString calls in this class and
  // monitor the length
  public static String jsonString(JSONObject object) {
    return object.toJSONString();
  }

  public static Date parseDate(String stringDate) {
    try {
      if (stringDate != null) {
        return DATE_FORMAT.parse(stringDate);
      }
    } catch (ParseException e) {
      ServerLogger.error("Error parsing JSON date: " + stringDate, e);
    }
    return null;
  }

  public static String getString(JSONObject json, String key) {
    return (String) json.get(key);
  }

  public static Long getLong(JSONObject json, String key) {
    return (Long) json.get(key);
  }

  public static Integer getInteger(JSONObject json, String key) {
    return JSONComposer.getLong(json, key).intValue();
  }

  public static Boolean getBoolean(JSONObject json, String key) {
    if (json.get(key) == null) {
      return Boolean.FALSE;
    }
    return (Boolean) json.get(key);
  }

  public static Date getDate(JSONObject json, String key) {
    return JSONComposer.parseDate((String) json.get(key));
  }
}
